package com.kexio.dynamic.permission.rule;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 权限规则模型
 * 
 * 定义动态权限规则的数据结构
 * 
 * @author Kexio
 * @since 1.0.0
 */
@Data
@TableName("kexio_permission_rules")
public class PermissionRule implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键ID
     */
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 规则名称
     */
    private String ruleName;

    /**
     * 规则代码（唯一标识）
     */
    private String ruleCode;

    /**
     * 资源标识
     */
    private String resource;

    /**
     * 操作动作
     */
    private String action;

    /**
     * 规则类型
     */
    private RuleType ruleType;

    /**
     * 规则表达式
     * 支持SpEL表达式、Groovy脚本等
     */
    private String ruleExpression;

    /**
     * 规则描述
     */
    private String description;

    /**
     * 规则优先级（数字越小优先级越高）
     */
    private Integer priority;

    /**
     * 是否启用
     */
    private Boolean enabled;

    /**
     * 规则条件（JSON格式）
     */
    private String conditions;

    /**
     * 规则参数（JSON格式）
     */
    private String parameters;

    /**
     * 生效时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime effectiveTime;

    /**
     * 失效时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime expireTime;

    /**
     * 租户ID
     */
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;

    /**
     * 创建时间
     */
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createdTime;

    /**
     * 更新时间
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updatedTime;

    /**
     * 创建者ID
     */
    @TableField(fill = FieldFill.INSERT)
    private Long createdBy;

    /**
     * 更新者ID
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updatedBy;

    /**
     * 乐观锁版本号
     */
    @Version
    @TableField(fill = FieldFill.INSERT)
    private Integer version;

    /**
     * 逻辑删除标记
     */
    @TableLogic
    @TableField(value = "deleted", fill = FieldFill.INSERT)
    private Integer deleted;

    /**
     * 检查规则是否在有效期内
     */
    public boolean isEffective() {
        if (!Boolean.TRUE.equals(enabled)) {
            return false;
        }
        
        LocalDateTime now = LocalDateTime.now();
        
        if (effectiveTime != null && now.isBefore(effectiveTime)) {
            return false;
        }
        
        if (expireTime != null && now.isAfter(expireTime)) {
            return false;
        }
        
        return true;
    }

    /**
     * 检查规则是否匹配指定的资源和动作
     */
    public boolean matches(String resource, String action) {
        if (!isEffective()) {
            return false;
        }
        
        return matchResource(resource) && matchAction(action);
    }

    /**
     * 匹配资源
     */
    private boolean matchResource(String targetResource) {
        if (this.resource == null || targetResource == null) {
            return false;
        }
        
        // 支持通配符匹配
        if (this.resource.contains("*")) {
            String pattern = this.resource.replace("*", ".*");
            return targetResource.matches(pattern);
        }
        
        return this.resource.equals(targetResource);
    }

    /**
     * 匹配动作
     */
    private boolean matchAction(String targetAction) {
        if (this.action == null || targetAction == null) {
            return false;
        }
        
        // 支持通配符匹配
        if (this.action.contains("*")) {
            String pattern = this.action.replace("*", ".*");
            return targetAction.matches(pattern);
        }
        
        return this.action.equals(targetAction);
    }

    // 手动添加getter方法以解决编译问题
    public String getRuleCode() {
        return ruleCode;
    }

    public void setRuleCode(String ruleCode) {
        this.ruleCode = ruleCode;
    }

    public RuleType getRuleType() {
        return ruleType;
    }

    public void setRuleType(RuleType ruleType) {
        this.ruleType = ruleType;
    }

    public String getRuleExpression() {
        return ruleExpression;
    }

    public void setRuleExpression(String ruleExpression) {
        this.ruleExpression = ruleExpression;
    }

    /**
     * 规则类型枚举
     */
    public enum RuleType {
        /**
         * SpEL表达式
         */
        SPEL("spel", "SpEL表达式"),
        
        /**
         * Groovy脚本
         */
        GROOVY("groovy", "Groovy脚本"),
        
        /**
         * JavaScript脚本
         */
        JAVASCRIPT("js", "JavaScript脚本"),
        
        /**
         * 简单条件
         */
        SIMPLE("simple", "简单条件"),
        
        /**
         * 复合规则
         */
        COMPOSITE("composite", "复合规则");

        private final String code;
        private final String description;

        RuleType(String code, String description) {
            this.code = code;
            this.description = description;
        }

        public String getCode() {
            return code;
        }

        public String getDescription() {
            return description;
        }

        public static RuleType fromCode(String code) {
            for (RuleType type : values()) {
                if (type.code.equals(code)) {
                    return type;
                }
            }
            return SIMPLE;
        }
    }
}
